package com.artisan.springuitls.demos;

import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.util.Map;

/**
 * UriComponentsBuilder 工具类演示
 * 功能：URL 构建安全专家
 * 优势：自动编码特殊字符，避免手写 URL 的 XSS 风险
 */
@Component
public class UriComponentsBuilderDemo {

    /**
     * 场景：拼接带参数的 URL
     */
    public String buildUrl() {
        System.out.println("\n========== UriComponentsBuilder Demo ==========");
        
        // ✅ 安全构建 URL：自动编码参数
        String url = UriComponentsBuilder.fromHttpUrl("http://localhost:8080/api")
            .queryParam("id", 1)
            .queryParam("name", "张三") // 自动编码中文
            .queryParam("tags", "java,spring") // 自动编码逗号
            .toUriString();
        
        System.out.println("✓ 构建的 URL: " + url);
        return url;
    }

    /**
     * 演示基础 URI 构建
     */
    public void demonstrateBasicUriBuilding() {
        System.out.println("\n--- 基础 URI 构建 ---");
        
        // 1. 从 HTTP URL 构建
        String url1 = UriComponentsBuilder
            .fromHttpUrl("https://api.example.com/users")
            .queryParam("page", 1)
            .queryParam("size", 20)
            .toUriString();
        System.out.println("✓ HTTP URL: " + url1);
        
        // 2. 从 URI 字符串构建
        String url2 = UriComponentsBuilder
            .fromUriString("https://api.example.com/users/{id}")
            .buildAndExpand(1001)
            .toUriString();
        System.out.println("✓ URI 模板: " + url2);
        
        // 3. 新建构建器
        String url3 = UriComponentsBuilder.newInstance()
            .scheme("https")
            .host("api.example.com")
            .port(8443)
            .path("/api/v1/users")
            .queryParam("status", "active")
            .toUriString();
        System.out.println("✓ 分段构建: " + url3);
        
        System.out.println();
    }

    /**
     * 演示路径变量
     */
    public void demonstratePathVariables() {
        System.out.println("\n--- 路径变量 ---");
        
        // 1. 单个路径变量
        String url1 = UriComponentsBuilder
            .fromUriString("https://api.example.com/users/{id}")
            .buildAndExpand(1001)
            .toUriString();
        System.out.println("✓ 单个变量: " + url1);
        
        // 2. 多个路径变量（按顺序）
        String url2 = UriComponentsBuilder
            .fromUriString("https://api.example.com/users/{userId}/orders/{orderId}")
            .buildAndExpand(1001, 5001)
            .toUriString();
        System.out.println("✓ 多个变量（顺序）: " + url2);
        
        // 3. 多个路径变量（使用 Map）
        Map<String, Object> vars = Map.of(
            "userId", 1001,
            "orderId", 5001
        );
        String url3 = UriComponentsBuilder
            .fromUriString("https://api.example.com/users/{userId}/orders/{orderId}")
            .buildAndExpand(vars)
            .toUriString();
        System.out.println("✓ 多个变量（Map）: " + url3);
        
        System.out.println();
    }

    /**
     * 演示查询参数处理
     */
    public void demonstrateQueryParameters() {
        System.out.println("\n--- 查询参数处理 ---");
        
        // 1. 单个参数
        String url1 = UriComponentsBuilder
            .fromHttpUrl("https://api.example.com/search")
            .queryParam("q", "Spring Boot")
            .toUriString();
        System.out.println("✓ 单个参数: " + url1);
        
        // 2. 多个参数
        String url2 = UriComponentsBuilder
            .fromHttpUrl("https://api.example.com/products")
            .queryParam("category", "电子产品")
            .queryParam("minPrice", 1000)
            .queryParam("maxPrice", 5000)
            .queryParam("sort", "price_asc")
            .toUriString();
        System.out.println("✓ 多个参数: " + url2);
        
        // 3. 参数值为数组
        String url3 = UriComponentsBuilder
            .fromHttpUrl("https://api.example.com/users")
            .queryParam("ids", 1, 2, 3, 4, 5)
            .toUriString();
        System.out.println("✓ 数组参数: " + url3);
        
        // 4. 可选参数（null 会被忽略）
        String search = null;
        String url4 = UriComponentsBuilder
            .fromHttpUrl("https://api.example.com/items")
            .queryParam("search", search)
            .queryParam("page", 1)
            .build()
            .toUriString();
        System.out.println("✓ 可选参数（null）: " + url4);
        
        // 5. 条件参数
        UriComponentsBuilder builder = UriComponentsBuilder
            .fromHttpUrl("https://api.example.com/users");
        
        String keyword = "张三";
        if (keyword != null && !keyword.isEmpty()) {
            builder.queryParam("keyword", keyword);
        }
        
        Integer minAge = 18;
        if (minAge != null) {
            builder.queryParam("minAge", minAge);
        }
        
        System.out.println("✓ 条件参数: " + builder.toUriString());
        
        System.out.println();
    }

    /**
     * 演示特殊字符编码
     */
    public void demonstrateEncoding() {
        System.out.println("\n--- 特殊字符编码 ---");
        
        // 1. 中文字符
        String url1 = UriComponentsBuilder
            .fromHttpUrl("https://api.example.com/search")
            .queryParam("q", "Spring Boot 教程")
            .toUriString();
        System.out.println("✓ 中文编码: " + url1);
        
        // 2. 特殊符号
        String url2 = UriComponentsBuilder
            .fromHttpUrl("https://api.example.com/search")
            .queryParam("q", "java & spring")
            .queryParam("tags", "java,spring,boot")
            .toUriString();
        System.out.println("✓ 特殊符号: " + url2);
        
        // 3. 空格处理
        String url3 = UriComponentsBuilder
            .fromHttpUrl("https://api.example.com/search")
            .queryParam("q", "hello world")
            .toUriString();
        System.out.println("✓ 空格编码: " + url3);
        
        // 4. URL 本身包含特殊字符
        String url4 = UriComponentsBuilder
            .fromHttpUrl("https://api.example.com/callback")
            .queryParam("redirect_uri", "https://app.com/auth?state=abc123")
            .toUriString();
        System.out.println("✓ URL 参数: " + url4);
        
        System.out.println();
    }

    /**
     * 演示 URI 解析和修改
     */
    public void demonstrateUriParsing() {
        System.out.println("\n--- URI 解析和修改 ---");
        
        String originalUrl = "https://api.example.com:8080/users/1001?status=active&role=admin#profile";
        
        // 解析 URI
        UriComponents components = UriComponentsBuilder
            .fromUriString(originalUrl)
            .build();
        
        System.out.println("✓ 原始 URL: " + originalUrl);
        System.out.println("✓ Scheme: " + components.getScheme());
        System.out.println("✓ Host: " + components.getHost());
        System.out.println("✓ Port: " + components.getPort());
        System.out.println("✓ Path: " + components.getPath());
        System.out.println("✓ Query: " + components.getQuery());
        System.out.println("✓ Fragment: " + components.getFragment());
        
        // 修改 URI
        String modifiedUrl = UriComponentsBuilder
            .fromUriString(originalUrl)
            .replacePath("/users/2002")
            .replaceQueryParam("status", "inactive")
            .fragment("settings")
            .toUriString();
        
        System.out.println("✓ 修改后 URL: " + modifiedUrl);
        
        System.out.println();
    }

    /**
     * 实际应用场景：API 客户端
     */
    public void demonstrateApiClient() {
        System.out.println("\n--- API 客户端场景 ---");
        
        String baseUrl = "https://api.example.com";
        
        // 1. 用户列表 API
        String listUsersUrl = UriComponentsBuilder
            .fromHttpUrl(baseUrl)
            .path("/api/v1/users")
            .queryParam("page", 1)
            .queryParam("size", 20)
            .queryParam("sort", "created_at,desc")
            .toUriString();
        System.out.println("✓ 用户列表: " + listUsersUrl);
        
        // 2. 用户详情 API
        Long userId = 1001L;
        String userDetailUrl = UriComponentsBuilder
            .fromHttpUrl(baseUrl)
            .path("/api/v1/users/{id}")
            .buildAndExpand(userId)
            .toUriString();
        System.out.println("✓ 用户详情: " + userDetailUrl);
        
        // 3. 搜索 API
        String searchUrl = UriComponentsBuilder
            .fromHttpUrl(baseUrl)
            .path("/api/v1/search")
            .queryParam("keyword", "Spring Boot")
            .queryParam("category", "技术")
            .queryParam("dateFrom", "2024-01-01")
            .queryParam("dateTo", "2024-12-31")
            .toUriString();
        System.out.println("✓ 搜索接口: " + searchUrl);
        
        System.out.println();
    }

    /**
     * 实际应用场景：OAuth 回调 URL
     */
    public void demonstrateOAuthCallback() {
        System.out.println("\n--- OAuth 回调 URL 场景 ---");
        
        String authUrl = UriComponentsBuilder
            .fromHttpUrl("https://oauth.provider.com/authorize")
            .queryParam("client_id", "your_client_id")
            .queryParam("redirect_uri", "https://yourapp.com/callback")
            .queryParam("response_type", "code")
            .queryParam("scope", "read write")
            .queryParam("state", "random_state_string")
            .toUriString();
        
        System.out.println("✓ OAuth 授权 URL:");
        System.out.println(authUrl);
        
        System.out.println();
    }

    /**
     * 演示与 RestTemplate 集成
     */
    public void demonstrateRestTemplateIntegration() {
        System.out.println("\n--- RestTemplate 集成 ---");
        
        URI uri = UriComponentsBuilder
            .fromHttpUrl("https://api.example.com/users/{id}")
            .queryParam("includeDetails", true)
            .buildAndExpand(1001)
            .toUri();
        
        System.out.println("✓ 生成的 URI: " + uri);
        System.out.println("✓ 可直接用于 RestTemplate:");
        System.out.println("  User user = restTemplate.getForObject(uri, User.class);");
        
        System.out.println("==========================================\n");
    }

    /**
     * 最佳实践
     */
    public void printBestPractices() {
        System.out.println("\n========== 最佳实践 ==========");
        System.out.println("✓ 1. 永远使用 UriComponentsBuilder 构建 URL");
        System.out.println("✓ 2. 不要手动拼接 URL 字符串（防 XSS）");
        System.out.println("✓ 3. 使用 queryParam() 自动编码参数");
        System.out.println("✓ 4. 路径变量用 {name} 占位符");
        System.out.println("✓ 5. 使用 buildAndExpand() 填充变量");
        System.out.println("✓ 6. toUri() 生成 URI 对象用于 HTTP 客户端");
        System.out.println("✓ 7. toUriString() 生成字符串用于日志/显示");
        System.out.println("✓ 8. 与 RestTemplate/WebClient 完美配合");
        System.out.println("==========================================\n");
    }
}

